package sso.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import sso.util.JwtUtils;
import sso.util.WebUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

//只做认证
/**构建配置安全对象*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    };

    /**
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //super.configure(http);
        //1.关闭跨域攻击
        http.csrf().disable();
        //2.配置form认证
        http.formLogin()
                .successHandler(successHandler())//登录成功
                .failureHandler(failureHandler());//登录失败
        http.exceptionHandling()
                .authenticationEntryPoint(entryPoint())//提示要认证
                .accessDeniedHandler(null);//提示访问被拒绝

        //3.所有资源都要认证
        http.authorizeRequests().anyRequest().authenticated();


    }
    /**登录成功后的认证处理器*/
    private AuthenticationSuccessHandler successHandler() {
        return (req, resp, auth) -> {
            Map<String,Object> map = new HashMap<>();
            map.put("state", 200);
            map.put("message", "Login ok");
            //返回一个令牌

            Map<String,Object> userInfo = new HashMap<>();
            User user = (User) auth.getPrincipal();
            userInfo.put("username", user.getUsername());
            List<String> authorities = new ArrayList<>();
            user.getAuthorities().forEach((authority)->{
                authorities.add(authority.getAuthority());
            });
            userInfo.put("authorities",authorities);//[sys:res:create,sys:res:retrieve]

            String token= JwtUtils.generatorToken(userInfo);
            map.put("token", token);
            WebUtils.writeJsonToClient(resp,map);
        };

    }

    /**登录失败的处理器*/
    private AuthenticationFailureHandler failureHandler(){
        return (req,resp,e)->{
            Map<String,Object> map = new HashMap<>();
            map.put("state", 500);
            map.put("message", "username or password error");
            WebUtils.writeJsonToClient(resp, map);

        };

    }
    /**假如没有登录访问资源时给出提示*/
    private AuthenticationEntryPoint entryPoint(){
        return (request,response, auth) -> {
              Map<String,Object> map=new HashMap<>();
              map.put("state", 401);
              map.put("message", "请先登录");
              WebUtils.writeJsonToClient(response, map);

        };

    }

}
